package myJson

import(
	"fmt"
	"reflect"
	"strings"
	//"errors"
)

func JsonMarshal(v interface {})([]byte, error)  {
	b, err := Marshal(v)
	if err != nil{
		return nil, err
	}
	return b, err	
}

func Marshal(v interface {})([]byte, error){
	//var b []byte
	//var err error
	if v == nil{
		return []byte("null"), nil
	}

	value := reflect.ValueOf(v)
	typeof := value.Type()
	ty := typeof.Kind()
	switch ty {
		
		case reflect.String:
			return []byte("\"" + value.String() + "\""), nil
		
		case reflect.Slice, reflect.Array:
			var b1 strings.Builder
			b1.WriteByte('[')
			for i := 0; i < value.Len(); i++{
				f1 :=value.Index(i)
				if i > 0{
					b1.WriteByte(',')
				}
				by1, err1 := Marshal(f1.Interface())
				if err1 != nil{
					return nil, err1
				}
				b1.Write(by1)
			}
			b1.WriteByte(']')
			return []byte(b1.String()), nil

		case reflect.Map:
			var b2 strings.Builder
			b2.WriteByte('{')
			item := value.MapRange()
			flag := true
			for item.Next(){
				if flag {
					flag = false
				}else{
					b2.WriteByte(',')
				}
				b2.WriteString(fmt.Sprintf("\"%v\":", item.Key()))
				by2, err2 := Marshal(item.Value().Interface())
				if err2 != nil{
					return nil, err2
				}
				b2.Write(by2)
			}
			b2.WriteByte('}')
			return []byte(b2.String()), nil
		
		case reflect.Struct:
			var b3 strings.Builder
			b3.WriteByte('{')
			for i := 0; i < value.NumField(); i++{
				f3 := value.Field(i)
				if i > 0{
					b3.WriteByte(',')
				}
				tag := typeof.Field(i).Tag.Get("mytag")
				if tag == ""{
					b3.WriteString(fmt.Sprintf("\"%s\":", typeof.Field(i).Name))
				}else{
					b3.WriteString(fmt.Sprintf("\"%s\":", tag))
				}
				by3, err3 := Marshal(f3.Interface())
				if err3 != nil{
					return nil, err3
				}
				b3.Write(by3)
			}
			b3.WriteByte('}')
			return []byte(b3.String()), nil
		
		case reflect.Ptr:
			return Marshal(value.Elem().Interface())

		default:
			return []byte(fmt.Sprintf("%v",value.Interface())), nil
	}

}